/**
   \file  string_utils.hh
   \brief String functions.
*/

/*
   This file is part of libgist.

   libgist is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.

   libgist is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with libgist; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/

/*
   REVISION HISTORY

   $HeadURL: http://libgist.googlecode.com/svn/branches/wu_dev/drv/string_utils.hh $
   $Id: string_utils.hh 42 2011-08-22 10:51:07Z libgist@gmail.com $
*/

#ifndef GISTDRV_STRING_UTILITIES_DOT_H
#define GISTDRV_STRING_UTILITIES_DOT_H

//------------------------------ HEADERS --------------------------------

// Standard C++ headers
#include <sstream>
#include <string>
#include <list>
#include <deque>
#include <vector>
#include <iterator>

//----------------------------- NAMESPACE -------------------------------

namespace gistdrv {

//--------------------- BASIC STRING CONVERSIONS ------------------------

/**
   \brief  Convert any object to an STL string.
   \param  t Reference to object to be converted to string.
   \return Object t in string form.

   Convenient (but perhaps not the most efficient) helper to convert
   various data types to strings.

   DEVNOTE: Works as long as type T defines an operator << that writes
   to an ostream.
*/
template<typename T>
std::string to_string(const T& t)
{
   std::ostringstream str ;
   str << t ;
   return str.str() ;
}

/**
   \brief  Convert an STL string to some type T.
   \param  s The string to be converted to T.
   \param  defval Default/initial value of s in case it can't be converted.
   \return The value of s as an instance of type T.

   This function read from the given string and returns the value as an
   instance of type T. It'll work as long as type T defines an operator
   >> that reads from an istream.

   If the string cannot be successfully converted to a T, the given
   default value will be returned instead of an exception being thrown.
   This default value is an optional parameter. Thus, if s cannot be
   converted to a T and the client does not specify a default value,
   it'll receive a default constructed version of T.
*/
template<typename T>
T from_string(const std::string& s, const T& defval = T())
{
   T t(defval) ;
   std::istringstream str(s) ;
   str >> t ;
   return t ;
}

// from_string() specialization for strings. If the client wants a string
// from the input string, we just return the input string. If we were to
// apply the default version of this template function, we would end up
// parsing the input string as a whitespace separated string stream and
// only return the first string from this stream.
template<>
inline std::string from_string(const std::string& s, const std::string&)
{
   return s ;
}

//-------------------------- STRING PARSING -----------------------------

/**
   \brief  Convert a whitespace separated string of T into a vector of T.
   \param  s The whitespace separated string to be parsed into a vector.
   \return An STL vector containing the values in s.

   This function splits a whitespace separated string into its
   "constituent" parts and stuffs each of them into an STL vector of T.
   Naturally, we assume the input string contains only things that can
   actually be converted to type T.
*/
template<typename T>
std::vector<T> string_to_vector(const std::string& s)
{
   std::istringstream str(s) ;
   return std::vector<T>(std::istream_iterator<T>(str),
                         std::istream_iterator<T>()) ;
}

/**
   \brief  Convert a whitespace separated string of T into a deque of T.
   \param  s The whitespace separated string to be parsed into a deque.
   \return An STL vector containing the values in s.

   This function splits a whitespace separated string into its
   "constituent" parts and stuffs each of them into an STL deque of T.
   Naturally, we assume the input string contains only things that can
   actually be converted to type T.
*/
/// Converts a whitespace separated string of T into a deque of T
template<typename T>
std::deque<T> string_to_deque(const std::string& s)
{
   std::istringstream str(s) ;
   return std::deque<T>(std::istream_iterator<T>(str),
                        std::istream_iterator<T>()) ;
}

/**
   \brief  Convert a whitespace separated string of T into a list of T.
   \param  s The whitespace separated string to be parsed into a list.
   \return An STL vector containing the values in s.

   This function splits a whitespace separated string into its
   "constituent" parts and stuffs each of them into an STL list of T.
   Naturally, we assume the input string contains only things that can
   actually be converted to type T.
*/
template<typename T>
std::list<T> string_to_list(const std::string& s)
{
   std::istringstream str(s) ;
   return std::list<T>(std::istream_iterator<T>(str),
                       std::istream_iterator<T>()) ;
}

//-----------------------------------------------------------------------

} // end of namespace encapsulating this file's definitions

#endif

/* So things look consistent in everyone's emacs... */
/* Local Variables: */
/* indent-tabs-mode: nil */
/* End: */
